/**
 * 在一个 n x n 的矩阵 grid 中，除了在数组 mines 中给出的元素为 0，其他每个元素都为 1。mines[i] = [xi, yi]表示 grid[xi][yi] == 0
 *
 * 返回  grid 中包含 1 的最大的 轴对齐 加号标志的阶数 。如果未找到加号标志，则返回 0 。
 *
 * 一个 k 阶由 1 组成的 “轴对称”加号标志 具有中心网格 grid[r][c] == 1 ，以及4个从中心向上、向下、向左、向右延伸，长度为 k-1，由 1 组成的臂。注意，只有加号标志的所有网格要求为 1 ，别的网格可能为 0 也可能为 1 。
 * https://leetcode.cn/problems/largest-plus-sign/description/
 * 思路：将每个方向的前缀和求出来
 */
class OrderOfLargestPlusSign {
    public int orderOfLargestPlusSign(int n, int[][] mines) {
        int[][] grid = new int[n][n];
        //初始化棋盘
        for(int[] a:grid) {
            Arrays.fill(a,1);
        }
        //填充0
        for(int[] m:mines) {
            grid[m[0]][m[1]] = 0;
        }
        int[][] left = new int[n][n];
        int[][] right = new int[n][n];
        int[][] top = new int[n][n];
        int[][] bottom = new int[n][n];
        //从左上遍历到右上
        for(int i=0;i<n;i++) {
            for(int j =0;j<n;j++) {
                if(grid[i][j]==1) {
                    //更新向右，向下方向
                    right[i][j] = (j==0?0:right[i][j-1])+1;
                    bottom[i][j] = (i==0?0:bottom[i-1][j])+1;
                }
            }
        }
        //从右下遍历到左下
        for(int i = n-1;i>=0;i--) {
            for(int j=n-1;j>=0;j--) {
                if(grid[i][j]==1) {
                    //更新向左，向上方向
                    left[i][j] = (j==n-1?0:left[i][j+1])+1;
                    top[i][j] = (i==n-1?0:top[i+1][j])+1;
                }
            }
        }
        int ans = 0;
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++) {
                //计算每个点位上下左右的最小值
                int min = Math.min(Math.min(left[i][j],right[i][j]),Math.min(top[i][j],bottom[i][j]));
                ans = Math.max(ans,min);
            }
        }
        return ans;
    }
}